﻿using Inovout.Cloud.Data.Blob.Models;
using Inovout.Runtime;
using Inovout.Services;
using Microsoft.Hadoop.WebHDFS;
using NHibernate.Criterion;
using System;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Inovout.Cloud.Data.Blob.Service
{
    public class FileService : RepositoryService<File>, IFileService
    {
        public bool Evict(string path)
        {
            return base.Repository.Exists(Restrictions.Eq("Path", path).IgnoreCase());
        }
        public File FindByPath(string path)
        {
            return base.Repository.Find(Restrictions.Eq("Path", path).IgnoreCase());
        }

        public File Create(Directory container, string name, long length)
        {
            File file = new File
            {
                Path = container.Path + name,
                Name = name,
                Directory = container,
                Owner = Thread.CurrentPrincipal.Identity.Name
                ,
                Length = length
            };
            base.Save(file);
            return file;
        }

        private WebHDFSClient GetWebHDFSClient(File file)
        {
            IApplication application = ComponentRegistry.Resolve<IApplication>();
            return new WebHDFSClient(new Uri(application.Settings["HdfsUri"].ToString()), file.Owner);
        }
        public  async Task<bool> UploadAsAsync(File file, System.IO.Stream fileStream)
        {
            var hdfsClient = GetWebHDFSClient(file);
            var result = await hdfsClient.CreateFile(fileStream, file).ConfigureAwait(false);
            return !string.IsNullOrEmpty(result);
        }
        public Task<bool> UploadAsAsync(string key, System.IO.Stream fileStream)
        {
            return UploadAsAsync(FindByKey(key), fileStream);
        }
        public Task<string> AppendUpload(File file, System.IO.Stream fileStream)
        {
            var hdfsClient = GetWebHDFSClient(file);
            return hdfsClient.AppendFile(fileStream, file.Path);
        }
        public  Task<System.IO.Stream> GetStreamAsync(File file, int offset, int length)
        {
            var hdfsClient = GetWebHDFSClient(file);
            return hdfsClient.OpenFile(file, offset, length);
        }

        public File FindByKey(string key)
        {
            return base.Repository.Find(NHibernate.Criterion.Restrictions.Eq("Key", key).IgnoreCase());
        }
        private async Task<bool> CompleteUploadAsAsync(File file)
        {
            //由于多线程保存会导致多个session。
            var hdfsClient = GetWebHDFSClient(file);
            return await hdfsClient.GetFileStatus(file).ContinueWith<bool>(
                t =>
                {
                    Logger.Info("CompleteUpload end:" + t.Result.Length.ToString());
                    file = this.FindById((object)file.Id);
                    if (file.Length == -1 && t.Result.Length > 0)
                    {
                        //临时解决
                        file.IsUploaded = true;
                        file.Length = t.Result.Length;
                        base.Save(file);
                        return true;
                    }
                    if (file.Length.Equals(t.Result.Length))
                    {
                        file.IsUploaded = true;
                        base.Save(file);
                        return true;
                    }
                    else
                    {
                        return false;
                    }

                }
                );

        }
        public async Task<bool> CompleteUploadAsAsync(string key)
        {
            return await CompleteUploadAsAsync(FindByKey(key));
        }


        public void Delete(File file)
        {
            if (file.IsUploaded)
            {
                var hdfsClient = GetWebHDFSClient(file);
                hdfsClient.DeleteDirectory(file.Path);
            }
            base.Delete((object)file.Id);
        }


        public async Task<bool> CopyAsAsync(File sourcefile, File destinationFile)
        {
            var hdfsClient = GetWebHDFSClient(sourcefile);
            return await hdfsClient.Copy(sourcefile, destinationFile).ContinueWith(
                t =>
                {
                    if (t.Result)
                    {
                        var result = hdfsClient.GetFileStatus(destinationFile).Result;
                        return result != null && result.Length.Equals(sourcefile.Length);
                    }
                    else
                    {
                        return false;
                    }
                }
                );
        }

        public System.IO.Stream GetLocalStream(File file)
        {
            System.IO.FileStream fileStream = new System.IO.FileStream(file.Path, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
            byte[] bytes = new byte[fileStream.Length];
            fileStream.Read(bytes, 0, bytes.Length);
            fileStream.Close();
            System.IO.Stream stream = new System.IO.MemoryStream(bytes);
            return stream;
        }


        public bool UploadLocalStream(string fileFullName, System.IO.Stream fileStream)
        {
            string dir = System.IO.Path.GetDirectoryName(fileFullName);
            if (!System.IO.Directory.Exists(dir))
            {
               System.IO.Directory.CreateDirectory(dir);
            }
            using (System.IO.FileStream fs = new System.IO.FileStream(fileFullName, System.IO.FileMode.Create))
            {
                try
                {
                    byte[] bytes = new byte[fileStream.Length];
                    fileStream.CopyTo(fs);
                    fs.Write(bytes, 0, bytes.Length);
                }
                catch (Exception e)
                {
                    return false;
                }
            }
            return true;
        }

    }
}